Commit | Line | Data |
---|---|---|
80f575fc DM |
1 | /* |
2 | * serialize.c | |
3 | * | |
4 | * Copyright (C) Georg Martius - January 2013 | |
5 | * georg dot martius at web dot de | |
6 | * | |
7 | * This file is part of vid.stab video stabilization library | |
8 | * | |
9 | * vid.stab is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License, | |
11 | * as published by the Free Software Foundation; either version 2, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * vid.stab is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with GNU Make; see the file COPYING. If not, write to | |
21 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | * | |
23 | */ | |
24 | ||
25 | #include <assert.h> | |
26 | #include <string.h> | |
27 | ||
28 | #include "serialize.h" | |
29 | #include "transformtype.h" | |
30 | #include "transformtype_operations.h" | |
31 | #include "motiondetect.h" | |
32 | ||
33 | const char* modname = "vid.stab - serialization"; | |
34 | ||
35 | ||
36 | int storeLocalmotion(FILE* f, const LocalMotion* lm){ | |
37 | return fprintf(f,"(LM %i %i %i %i %i %lf %lf)", lm->v.x,lm->v.y,lm->f.x,lm->f.y,lm->f.size, | |
38 | lm->contrast, lm->match); | |
39 | } | |
40 | ||
41 | /// restore local motion from file | |
42 | LocalMotion restoreLocalmotion(FILE* f){ | |
43 | LocalMotion lm; | |
44 | char c; | |
45 | if(fscanf(f,"(LM %i %i %i %i %i %lf %lf", &lm.v.x,&lm.v.y,&lm.f.x,&lm.f.y,&lm.f.size, | |
46 | &lm.contrast, &lm.match) != 7) { | |
47 | vs_log_error(modname, "Cannot parse localmotion!\n"); | |
48 | return null_localmotion(); | |
49 | } | |
50 | while((c=fgetc(f)) && c!=')' && c!=EOF); | |
51 | if(c==EOF){ | |
52 | vs_log_error(modname, "Cannot parse localmotion missing ')'!\n"); | |
53 | return null_localmotion(); | |
54 | } | |
55 | return lm; | |
56 | } | |
57 | ||
58 | int vsStoreLocalmotions(FILE* f, const LocalMotions* lms){ | |
59 | int len = vs_vector_size(lms); | |
60 | int i; | |
61 | fprintf(f,"List %i [",len); | |
62 | for (i=0; i<len; i++){ | |
63 | if(i>0) fprintf(f,","); | |
64 | if(storeLocalmotion(f,LMGet(lms,i)) <= 0) return 0; | |
65 | } | |
66 | fprintf(f,"]"); | |
67 | return 1; | |
68 | } | |
69 | ||
70 | /// restores local motions from file | |
71 | LocalMotions vsRestoreLocalmotions(FILE* f){ | |
72 | LocalMotions lms; | |
73 | int i; | |
74 | char c; | |
75 | int len; | |
76 | vs_vector_init(&lms,0); | |
77 | if(fscanf(f,"List %i [", &len) != 1) { | |
78 | vs_log_error(modname, "Cannot parse localmotions list expect 'List len ['!\n"); | |
79 | return lms; | |
80 | } | |
81 | if (len>0){ | |
82 | vs_vector_init(&lms,len); | |
83 | for (i=0; i<len; i++){ | |
84 | if(i>0) while((c=fgetc(f)) && c!=',' && c!=EOF); | |
85 | LocalMotion lm = restoreLocalmotion(f); | |
86 | vs_vector_append_dup(&lms,&lm,sizeof(LocalMotion)); | |
87 | } | |
88 | } | |
89 | if(len != vs_vector_size(&lms)){ | |
90 | vs_log_error(modname, "Cannot parse the given number of localmotions!\n"); | |
91 | return lms; | |
92 | } | |
93 | while((c=fgetc(f)) && c!=']' && c!=EOF); | |
94 | if(c==EOF){ | |
95 | vs_log_error(modname, "Cannot parse localmotions list missing ']'!\n"); | |
96 | return lms; | |
97 | } | |
98 | return lms; | |
99 | } | |
100 | ||
101 | int vsPrepareFile(const VSMotionDetect* md, FILE* f){ | |
102 | if(!f) return VS_ERROR; | |
103 | fprintf(f, "VID.STAB 1\n"); | |
104 | fprintf(f, "# accuracy = %d\n", md->conf.accuracy); | |
105 | fprintf(f, "# shakiness = %d\n", md->conf.shakiness); | |
106 | fprintf(f, "# stepsize = %d\n", md->conf.stepSize); | |
107 | fprintf(f, "# mincontrast = %f\n", md->conf.contrastThreshold); | |
108 | return VS_OK; | |
109 | } | |
110 | ||
111 | int vsWriteToFile(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){ | |
112 | if(!f || !lms) return VS_ERROR; | |
113 | ||
114 | if(fprintf(f, "Frame %i (", md->frameNum)>0 | |
115 | && vsStoreLocalmotions(f,lms)>0 && fprintf(f, ")\n")) | |
116 | return VS_OK; | |
117 | else | |
118 | return VS_ERROR; | |
119 | } | |
120 | ||
121 | /// reads the header of the file and return the version number | |
122 | int vsReadFileVersion(FILE* f){ | |
123 | if(!f) return VS_ERROR; | |
124 | int version; | |
125 | if(fscanf(f, "VID.STAB %i\n", &version)!=1) | |
126 | return VS_ERROR; | |
127 | else return version; | |
128 | } | |
129 | ||
130 | int vsReadFromFile(FILE* f, LocalMotions* lms){ | |
131 | char c = fgetc(f); | |
132 | if(c=='F') { | |
133 | int num; | |
134 | if(fscanf(f,"rame %i (", &num)!=1) { | |
135 | vs_log_error(modname,"cannot read file, expect 'Frame num (...'"); | |
136 | return VS_ERROR; | |
137 | } | |
138 | *lms = vsRestoreLocalmotions(f); | |
139 | if(fscanf(f,")\n")<0) { | |
140 | vs_log_error(modname,"cannot read file, expect '...)'"); | |
141 | return VS_ERROR; | |
142 | } | |
143 | return num; | |
144 | } else if(c=='#') { | |
145 | char l[1024]; | |
146 | if(fgets(l, sizeof(l), f)==0) return VS_ERROR; | |
147 | return vsReadFromFile(f,lms); | |
148 | } else if(c=='\n' || c==' ') { | |
149 | return vsReadFromFile(f,lms); | |
150 | } else if(c==EOF) { | |
151 | return VS_ERROR; | |
152 | } else { | |
153 | vs_log_error(modname,"cannot read frame local motions from file, got %c (%i)", | |
154 | c, (int) c); | |
155 | return VS_ERROR; | |
156 | } | |
157 | } | |
158 | ||
159 | int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* mlms){ | |
160 | int version = vsReadFileVersion(f); | |
161 | if(version<1) // old format or unknown | |
162 | return VS_ERROR; | |
163 | if(version>1){ | |
164 | vs_log_error(modname,"Version of VID.STAB file too large: got %i, expect <= 1", | |
165 | version); | |
166 | return VS_ERROR; | |
167 | } | |
168 | assert(mlms); | |
169 | // initial number of frames, but it will automatically be increaseed | |
170 | vs_vector_init(mlms,1024); | |
171 | int index; | |
172 | int oldindex = 0; | |
173 | LocalMotions lms; | |
174 | while((index = vsReadFromFile(f,&lms)) != VS_ERROR){ | |
175 | if(index > oldindex+1){ | |
176 | vs_log_info(modname,"VID.STAB file: index of frames is not continuous %i -< %i", | |
177 | oldindex, index); | |
178 | } | |
179 | if(index<1){ | |
180 | vs_log_info(modname,"VID.STAB file: Frame number < 1 (%i)", index); | |
181 | } else { | |
182 | vs_vector_set_dup(mlms,index-1,&lms, sizeof(LocalMotions)); | |
183 | } | |
184 | oldindex=index; | |
185 | } | |
186 | return VS_OK; | |
187 | } | |
188 | ||
189 | ||
190 | /** | |
191 | * vsReadOldTransforms: read transforms file (Deprecated format) | |
192 | * The format is as follows: | |
193 | * Lines with # at the beginning are comments and will be ignored | |
194 | * Data lines have 5 columns seperated by space or tab containing | |
195 | * time, x-translation, y-translation, alpha-rotation, extra | |
196 | * where time and extra are integers | |
197 | * and the latter is unused at the moment | |
198 | * | |
199 | * Parameters: | |
200 | * f: file description | |
201 | * trans: place to store the transforms | |
202 | * Return value: | |
203 | * number of transforms read | |
204 | * Preconditions: f is opened | |
205 | */ | |
206 | int vsReadOldTransforms(const VSTransformData* td, FILE* f , VSTransformations* trans) | |
207 | { | |
208 | char l[1024]; | |
209 | int s = 0; | |
210 | int i = 0; | |
211 | int ti; // time (ignored) | |
212 | VSTransform t; | |
213 | ||
214 | while (fgets(l, sizeof(l), f)) { | |
215 | t = null_transform(); | |
216 | if (l[0] == '#') | |
217 | continue; // ignore comments | |
218 | if (strlen(l) == 0) | |
219 | continue; // ignore empty lines | |
220 | // try new format | |
221 | if (sscanf(l, "%i %lf %lf %lf %lf %i", &ti, &t.x, &t.y, &t.alpha, | |
222 | &t.zoom, &t.extra) != 6) { | |
223 | if (sscanf(l, "%i %lf %lf %lf %i", &ti, &t.x, &t.y, &t.alpha, | |
224 | &t.extra) != 5) { | |
225 | vs_log_error(td->conf.modName, "Cannot parse line: %s", l); | |
226 | return 0; | |
227 | } | |
228 | t.zoom=0; | |
229 | } | |
230 | ||
231 | if (i>=s) { // resize transform array | |
232 | if (s == 0) | |
233 | s = 256; | |
234 | else | |
235 | s*=2; | |
236 | /* vs_log_info(td->modName, "resize: %i\n", s); */ | |
237 | trans->ts = vs_realloc(trans->ts, sizeof(VSTransform)* s); | |
238 | if (!trans->ts) { | |
239 | vs_log_error(td->conf.modName, "Cannot allocate memory" | |
240 | " for transformations: %i\n", s); | |
241 | return 0; | |
242 | } | |
243 | } | |
244 | trans->ts[i] = t; | |
245 | i++; | |
246 | } | |
247 | trans->len = i; | |
248 | ||
249 | return i; | |
250 | } | |
251 | ||
252 | ||
253 | // t = vsSimpleMotionsToTransform(md, &localmotions); | |
254 | ||
255 | ||
256 | /* | |
257 | * Local variables: | |
258 | * c-file-style: "stroustrup" | |
259 | * c-file-offsets: ((case-label . *) (statement-case-intro . *)) | |
260 | * indent-tabs-mode: nil | |
261 | * c-basic-offset: 2 t | |
262 | * End: | |
263 | * | |
264 | * vim: expandtab shiftwidth=2: | |
265 | */ |