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