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
storeLocalmotion(FILE * f,const LocalMotion * lm)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
restoreLocalmotion(FILE * f)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
vsStoreLocalmotions(FILE * f,const LocalMotions * lms)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
vsRestoreLocalmotions(FILE * f)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
vsPrepareFile(const VSMotionDetect * md,FILE * f)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
vsWriteToFile(const VSMotionDetect * md,FILE * f,const LocalMotions * lms)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
vsReadFileVersion(FILE * f)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
vsReadFromFile(FILE * f,LocalMotions * lms)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
vsReadLocalMotionsFile(FILE * f,VSManyLocalMotions * mlms)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 */
vsReadOldTransforms(const VSTransformData * td,FILE * f,VSTransformations * trans)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 */
266