Hugin trunk 0.1
Loading...
Searching...
No Matches
pto_move.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
12/* This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This software is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public
23 * License along with this software. If not, see
24 * <http://www.gnu.org/licenses/>.
25 *
26 */
27
28#include "hugin_config.h"
29#include <iostream>
30#include <string>
31#include <fstream>
32#include <filesystem>
33#include <getopt.h>
34#include <panodata/Panorama.h>
36
37std::string IncludeTrailingDelimiter(std::string path)
38{
39 std::string s=path;
40#ifdef _WIN32
41 if(s.compare(s.length()-1,1,"\\")!=0 && s.compare(s.length()-1,1,"/")!=0)
42 {
43 s.append("\\");
44 };
45#else
46 if(s.compare(s.length()-1,1,"/")!=0)
47 {
48 s.append("/");
49 };
50#endif
51 return s;
52};
53
54// rebase a filename from relative to srcPath to relative to destPath and return absolute new dest path
55bool RebaseFilename(std::filesystem::path srcFile, std::filesystem::path& destFile, std::string srcPath, std::string destPath)
56{
57 std::filesystem::path input=std::filesystem::absolute(srcFile);
58 std::string fullInputPath=input.string();
61 {
62 return false;
63 };
65 destFile=std::filesystem::path(fullInputPath);
66 return true;
67};
68
69bool checkDestinationDirectory(std::string dir, std::filesystem::path& pathTo)
70{
71 pathTo=std::filesystem::path(dir);
72 try
73 {
74 // check if a destination directory is given
75 if(pathTo.extension().string().length()>0)
76 {
77 std::cerr << "ERROR: Your destination is a file. Copy/Move several files to " << std::endl
78 << "a single file is not allowed." << std::endl
79 << "Canceled operation." << std::endl;
80 return false;
81 };
82 // create destination directory if not exists
83 if(!std::filesystem::exists(pathTo))
84 {
85 if(!std::filesystem::create_directories(pathTo))
86 {
87 std::cerr << "ERROR: Could not create destination directory: " << pathTo.string() << std::endl
88 << "Maybe you have not sufficient rights to create this directory." << std::endl;
89 return false;
90 };
91 };
92 }
93 catch (const std::filesystem::filesystem_error& ex)
94 {
95 std::cout << ex.what() << std::endl;
96 return false;
97 }
98 pathTo=std::filesystem::absolute(pathTo);
99 return true;
100};
101
102typedef std::set<std::filesystem::path> pathVec;
103
104bool PTOCopyMove(bool movingFile, std::filesystem::path src, std::filesystem::path dest, bool overwriteAllFiles)
105{
106 std::filesystem::path destFile(hugin_utils::GetAbsoluteFilename(dest.string()));
107 std::cout << (movingFile ? "Moving project file " : "Copying project file ") << src.filename() << std::endl
108 << " from " << src.parent_path().string() << std::endl
109 << " to " << destFile.parent_path().string() << std::endl;
110 // open project file
112 const std::string input=src.string();
114 const std::string outputPathPrefix = hugin_utils::getPathPrefix(destFile.string());
116 {
117 return false;
118 };
120 std::map<std::filesystem::path,std::filesystem::path> imagesTo;
121 // check if all images exists
122 for(size_t i=0; i<pano.getNrOfImages(); i++)
123 {
124 std::filesystem::path p(pano.getImage(i).getFilename());
125 if(!std::filesystem::exists(p) || !std::filesystem::is_regular_file(p))
126 {
127 std::cerr << "ERROR: image " << p.string() << " not found on disc." << std::endl
128 << "Skipping project " << input << std::endl;
129 return false;
130 };
131 p=std::filesystem::absolute(p);
132 auto result = imagesFrom.insert(p);
133 if (!result.second)
134 {
135 // file is already in list,
136 // update also this filename in pto file
137 pano.setImageFilename(i, imagesTo[p].string());
138 continue;
139 };
140 // now build now image filename
141 std::filesystem::path newFilename;
143 {
144 pano.setImageFilename(i, newFilename.string());
146 };
147 };
148 if(!imagesFrom.empty())
149 {
150 if(imagesFrom.size()==imagesTo.size())
151 {
152 std::filesystem::path targetDir(destFile);
153 targetDir.remove_filename();
155 {
156 return false;
157 };
158 if(std::filesystem::exists(destFile) && !overwriteAllFiles)
159 {
160 std::cout << "Project file " << destFile << " does already exists." << std::endl
161 << " Overwrite this file? [Y|N] ";
162 std::string userAnswer;
163 while(userAnswer.length()==0)
164 {
165 std::cin >> userAnswer;
166 };
168 if(userAnswer!="YES" && userAnswer!="Y")
169 {
170 std::cout << std::endl << "Moving/Copying of project file " << input << " canceled." << std::endl << std::endl;
171 return false;
172 }
173 };
174 //copy/moving images
175 for(const auto& imgFrom: imagesFrom)
176 {
177 // check if target directory already exists
179 targetDir.remove_filename();
181 {
182 return false;
183 };
184 //check if target image file already exists
185 if(std::filesystem::exists(imagesTo[imgFrom]) && !overwriteAllFiles)
186 {
187 std::cout << "Images file " << imagesTo[imgFrom] << " does already exists." << std::endl
188 << " Overwrite this file? [Y|N] ";
189 std::string userAnswer;
190 while(userAnswer.length()==0)
191 {
192 std::cin >> userAnswer;
193 };
195 if(userAnswer!="YES" && userAnswer!="Y")
196 {
197 std::cout << std::endl << "Moving/Copying of project file " << input << " canceled." << std::endl << std::endl;
198 return false;
199 }
200 };
201 if(movingFile)
202 {
203 try
204 {
205 std::filesystem::rename(imgFrom, imagesTo[imgFrom]);
206 }
207 catch (const std::filesystem::filesystem_error& ex)
208 {
209 std::cout << ex.what() << std::endl;
210 return false;
211 }
212 }
213 else
214 {
215 try
216 {
217 std::filesystem::copy_file(imgFrom, imagesTo[imgFrom], std::filesystem::copy_options::overwrite_existing);
218 }
219 catch (const std::filesystem::filesystem_error& ex)
220 {
221 std::cout << ex.what() << std::endl;
222 return false;
223 }
224 };
225 }; // for loop for all images
226 // now create pano file in new destination
227 // write output
228 if (!pano.WritePTOFile(destFile.string(), outputPathPrefix))
229 {
230 return false;
231 };
232 if(movingFile)
233 {
234 try
235 {
236 std::filesystem::remove(src);
237 }
238 catch (const std::filesystem::filesystem_error& ex)
239 {
240 std::cout << "Could not remove original file: " << input << std::endl;
241 std::cout << ex.what() << std::endl;
242 return false;
243 }
244 };
245 }
246 else
247 {
248 // the images in the project file are not all relative to the same base path
249 std::cout << "WARNING: Images location in project file are not consistent. " << std::endl
250 << "So don't move/copy project file " << src.string() << std::endl;
251 return false;
252 };
253 }
254 else
255 {
256 // now create pano file in new destination, project contains images in paths
257 // not relative to base directory
258 // so create only the new project file without copying/moving image files
259 if (!pano.WritePTOFile(destFile.string(), outputPathPrefix))
260 {
261 return false;
262 };
263 if(movingFile)
264 {
265 try
266 {
267 std::filesystem::remove(src);
268 }
269 catch (const std::filesystem::filesystem_error& ex)
270 {
271 std::cout << "Could not remove original file: " << input << std::endl;
272 std::cout << ex.what() << std::endl;
273 return false;
274 }
275 };
276 };
277 return true;
278};
279
280template <class iteratorType>
281bool iterateFileSystem(std::string src, pathVec& projectFiles)
282{
283 try
284 {
285 for(iteratorType it(src); it != iteratorType(); it++)
286 {
287 std::string ext=hugin_utils::toupper(it->path().extension().string());
288 if(ext==".PTO")
289 {
290 projectFiles.insert(*it);
291 };
292 }
293 }
294 catch(std::filesystem::filesystem_error& e)
295 {
296 std::cout << e.what() << std::endl;
297 return false;
298 }
299 return true;
300};
301
302void SearchPTOFilesInDirectory(pathVec& projectFiles, std::string src, bool recursive)
303{
304 if(recursive)
305 {
307 }
308 else
309 {
311 };
312};
313
314static void usage(const char* name)
315{
316 std::cout << name << ": move a project file with all images in it" << std::endl
317 << name << " version " << hugin_utils::GetHuginVersion() << std::endl
318 << std::endl
319 << "Usage: pto_move [options] path1/source.pto path2/dest.pto" << std::endl
320 << " Rename project file path1/source.pto to " << std::endl
321 << " path2/dest.pto. All images contained in the project will" << std::endl
322 << " be moved accordingly." << std::endl << std::endl
323 << " pto_move [options] sourceFolder destFolder" << std::endl
324 << " Moves all project files in the source folder to " << std::endl
325 << " the destination folder including all images." << std::endl
326 << std::endl
327 << "Options: " << std::endl
328 << " --copy Copy project files and images instead of moving" << std::endl
329 << " --recursive Only effective in use case 2. Go recursive in the" << std::endl
330 << " the source folder and move all project files with images" << std::endl
331 << " to destination folder by maintaining the folder structure" << std::endl
332 << " relative to source folder." << std::endl
333 << " --overwrite Overwrite all existing files. Otherwise you will be asked" << std::endl
334 << " for each existing file." << std::endl
335 << std::endl
336 << std::endl;
337};
338
339int main(int argc, char* argv[])
340{
341 // parse arguments
342 const char* optstring = "croh";
343
344 static struct option longOptions[] =
345 {
346 {"copy", no_argument, NULL, 'c' },
347 {"recursive", no_argument, NULL, 'r' },
348 {"overwrite", no_argument, NULL, 'o' },
349 {"help", no_argument, NULL, 'h' },
350 0
351 };
352
353 bool movingFiles=true; //movingFiles: false->copy, true->move
354 bool recursive=false;
355 bool forceOverwrite=false;
356 int c;
357 while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
358 {
359 switch (c)
360 {
361 case 'h':
363 return 0;
364 case 'c':
365 movingFiles=false;
366 break;
367 case 'r':
368 recursive=true;
369 break;
370 case 'o':
371 forceOverwrite=true;
372 break;
373 case ':':
374 case '?':
375 // missing argument or invalid switch
376 return 1;
377 break;
378 default:
379 // this should not happen
380 abort();
381 }
382 }
383
384 if(argc-optind<2)
385 {
386 std::cerr << hugin_utils::stripPath(argv[0]) << ": You need to give at least a source and a destination project file or directory." << std::endl;
387 return 1;
388 };
389
390 try
391 {
392 std::filesystem::path p(argv[optind]);
393 if(std::filesystem::exists(p))
394 {
395 p=std::filesystem::absolute(p);
396 if(std::filesystem::is_directory(p))
397 {
398 // first parameter is a directory
399 std::filesystem::path pathTo;
400 if(!checkDestinationDirectory(std::string(argv[argc-1]), pathTo))
401 {
402 return 1;
403 };
404 // search all pto files in directory
405 pathVec projectFiles;
406 std::cout << "Searching project files in " << p << std::endl;
407 SearchPTOFilesInDirectory(projectFiles, p.string(), recursive);
408 if(projectFiles.empty())
409 {
410 std::cout << "No project files found in given directory " << p.string() << std::endl;
411 return 0;
412 };
413 std::cout << "Found " << projectFiles.size() << " project files." << std::endl << std::endl;
414 for(pathVec::const_iterator it=projectFiles.cbegin(); it!=projectFiles.cend(); ++it)
415 {
416 std::filesystem::path newPath;
417 if(RebaseFilename(*it, newPath, p.string(), pathTo.string()))
418 {
420 };
421 };
422 }
423 else
424 {
425 if(argc-optind>2)
426 {
427 // several files given
428 // check if destination is a directory and create it if necessary
429 std::filesystem::path pathTo;
430 if(!checkDestinationDirectory(std::string(argv[argc-1]), pathTo))
431 {
432 return 1;
433 };
434 while(optind<argc-1)
435 {
436 p=std::filesystem::path(argv[optind]);
437 std::string ext=hugin_utils::toupper(p.extension().string());
438 // work only on pto files
439 if(ext==".PTO")
440 {
441 if(std::filesystem::exists(p) && std::filesystem::is_regular_file(p))
442 {
443 p=std::filesystem::absolute(p);
444 std::filesystem::path newPath = pathTo / p.filename();
446 }
447 else
448 {
449 std::cout << "WARNING: File " << p << " does not exists" << std::endl
450 << "Skipping this file." << std::endl;
451 };
452 };
453 optind++;
454 };
455 }
456 else
457 {
458 // exactly 2 files given
459 std::filesystem::path pathTo(argv[argc-1]);
460 if(pathTo.extension().string().length()>0)
461 {
462 // user has given filename with extension
463 // so simply copy/move file
464 pathTo=std::filesystem::absolute(pathTo);
466 }
467 else
468 {
469 // target is a directory
470 if(!checkDestinationDirectory(std::string(argv[argc-1]), pathTo))
471 {
472 return 1;
473 };
474 pathTo=pathTo / p.filename();
475 if(p==pathTo)
476 {
477 std::cerr << "ERROR: Target and destination file are the same." << std::endl
478 << "Skipping file processing." << std::endl;
479 return 1;
480 };
482 };
483 };
484 };
485 };
486 }
487 catch (const std::filesystem::filesystem_error& ex)
488 {
489 std::cout << ex.what() << std::endl;
490 }
491 return 0;
492}
static void usage()
Definition Main.cpp:32
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
void setImageFilename(unsigned int img, const std::string &fname)
set a new image filename
Definition Panorama.cpp:373
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
std::vector< std::filesystem::path > pathVec
std::string toupper(const std::string &s)
Definition stl_utils.h:59
std::string GetAbsoluteFilename(const std::string &filename)
returns the full absolute filename
Definition utils.cpp:368
std::string GetHuginVersion()
return a string with version numbers
Definition utils.cpp:907
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition utils.cpp:160
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition utils.cpp:184
int main(int argc, char *argv[])
Definition pto_move.cpp:339
std::set< std::filesystem::path > pathVec
Definition pto_move.cpp:102
void SearchPTOFilesInDirectory(pathVec &projectFiles, std::string src, bool recursive)
Definition pto_move.cpp:302
bool PTOCopyMove(bool movingFile, std::filesystem::path src, std::filesystem::path dest, bool overwriteAllFiles)
Definition pto_move.cpp:104
bool checkDestinationDirectory(std::string dir, std::filesystem::path &pathTo)
Definition pto_move.cpp:69
bool iterateFileSystem(std::string src, pathVec &projectFiles)
Definition pto_move.cpp:281
bool RebaseFilename(std::filesystem::path srcFile, std::filesystem::path &destFile, std::string srcPath, std::string destPath)
Definition pto_move.cpp:55
std::string IncludeTrailingDelimiter(std::string path)
Definition pto_move.cpp:37
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41