1 // Slideshow.cpp - Convert a directory tree into an html page
2 // forming a slideshow of all image files in
3 // the directory tree.
4 // Operating Systems: Win95, Win98, WinNT, Win2000.
5 // Images supported - PPM/JPEG/GIF/TIFF/PNG/BMP
6 // Version 1.6
7
8 // Copyright (C) 2001 Anand B Pillai
9 // Copyright (C) 2001 Free Software Foundation, Inc.
10 //
11 // Author: Anand B Pillai <anandpillai@hotmail.com>, <mallucoder@sourceforge.net>
12 // Keywords: HTML application, Graphics
13
14 // This program is free software; you can redistribute it and/or
15 // modify it under the terms of the GNU General Public License
16 // as published by the Free Software Foundation; either version 2
17 // of the License, or (at your option) any later version.
18
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
28 // History
29 // Modification Date Coder
30 //
31 // Fixed directory path bug pointed out by Karthikeyan 01/01/2002 Anand
32 // Added support for gif/png/bmp files 01/01/2002 Anand
33 // Added button to restart show 01/01/2002 Anand
34 // Fixed problem for netscape with '.' and '..' directories
35 // (Get the complete directory name everytime) 01/01/2002 Anand
36 // Added javascript code to identify browser 01/01/2002 Anand
37 // Fixed problem for netscape with bmp files 01/01/2002 Anand
38 // (Used javascript trick to avoid bmp files showing in netscape!)
39 // Added support for reveal transitions (default is a revealtrans of 5) 01/01/2002 Anand
40 // Added transition as command line option
41
42 #ifndef _WIN32
43 #pragma warning("Error: unsupported operating system")
44 #endif
45
46 #include <iostream>
47 #include <fstream>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <windows.h>
51 #include <stdlib.h>
52
53 using namespace std;
54
55 const int MAXSIZ=1024;
56 const int NUM_IMG_TYPES=10;
57 const int OK=1;
58 const int KO=0;
59
60 typedef struct
61 {
62 int speedofshow;
63 char directory[MAXSIZ];
64 int blend;
65 int duration;
66 int transition;
67 int border;
68 char* title;
69 int norecurse;
70 }
71 Options;
72
73
74 static char* isImage(char *);
75 static int parseArgs( int, char**, Options* );
76 void printTree(char *);
77 static ofstream out("slideshow.html", ios::trunc );
78 static char first_img[MAXSIZ];
79 static Options opt;
80
81
82 static char* imageExtns[NUM_IMG_TYPES] = {".jpg", ".jpeg", ".JPG", ".JPEG", ".gif", ".GIF", ".png", ".PNG", ".bmp", ".BMP" };
83 main(int argc, char* argv[])
84 {
85 int border;
86 long timeout;
87 int crossfadedurn;
88 char title[MAXSIZ];
89 int rel_to_cd=KO;
90 int blend=KO;
91 int transnumber;
92
93
94 if ( argc < 2 )
95 {
96 cout << "Usage: " << argv[0] <<" -d <directory> [Optional] \n";
97 cout << "\t [Optional] arguments \n\n";
98 cout << " -norec [dont recurse into subdirectories(default is recurse)]\n";
99 cout << " -t [time between frames in milliseconds]\n";
100 cout << " -cf [crossfade duration in milliseconds]\n";
101 cout << " -b [border width in pixels]\n";
102 cout << " -tt [title of the show]\n";
103 cout << " --blendtrans [duration in seconds]\n";
104 cout << " --revealtrans [duration in seconds] [transition number (0-23)]\n";
105
106 exit(1);
107 }
108
109 int ret = parseArgs( argc, argv, &opt );
110 if ( ret == -1 )
111 {
112 cerr << "Error in arguments!!\n";
113 exit(2);
114 }
115
116 border = opt.border;
117 timeout = opt.speedofshow;
118 strcpy( title, opt.title );
119 blend = opt.blend;
120 crossfadedurn = opt.duration;
121 transnumber = opt.transition;
122
123
124 out << "<HTML>\n";
125 out << "<HEAD>\n";
126 out <<"<!-- Geneated by Image2Html Creater Version 1.0 -->\n";
127 out << "<script language=\"Javascript\">\n";
128 out << "// Browser detection \n";
129 out << "var agt=navigator.userAgent.toLowerCase()\n";
130 out << "var is_major = parseInt(navigator.appVersion)\n";
131 out << "var is_minor = parseFloat(navigator.appVersion)\n";
132 out << "var is_ie = ((agt.indexOf(\"msie\") != -1) && (agt.indexOf(\"opera\") == -1))\n";
133 out << "var is_nav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)\n";
134 out << " && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)\n";
135 out << " && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1))\n";
136 out << "var is_gecko = (agt.indexOf('gecko') != -1)\n";
137 out << "var slideShowSpeed = " << timeout << "\n";
138 out << "var crossFadeDuration = " << crossfadedurn << "\n";
139 if ( blend == 0 )
140 {
141 out << "var trans = " << transnumber << "\n";
142 }
143 out << "var bmpExp1 = /.bmp/\n";
144 out << "var bmpExp2 = /.BMP/\n";
145 out << "var found\n";
146 out << "var Pic = new Array()\n";
147
148 // check if the directory is relative to the current directory
149 if ( opt.directory[0] == '.' )
150 rel_to_cd = OK;
151
152 if ( rel_to_cd )
153 {
154 // get full path name of directory
155 #ifdef _WIN32
156 char cwd[MAXSIZ];
157
158 if ( _fullpath( cwd, opt.directory, MAXSIZ ))
159 strcpy( opt.directory, cwd );
160
161 cerr << cwd << endl;
162 #endif
163 }
164
165 printTree( opt.directory );
166
167
168 out << "var t\n" << "var ii = 0\n" << "var j = 0\n" << "var p = Pic.length\n" << "var preLoad = new Array()\n";
169
170 out << " for(var i=0; i<p; i++ ) {\n";
171 out << "if ( (is_ie) || ((is_nav || is_gecko) && !bmpExp1.test(Pic[i]) && !bmpExp2.test(Pic[i]))){ \n";
172 out << " preLoad[ii] = new Image()\n";
173 out << " preLoad[ii].src = Pic[i]\n";
174 out << "ii++\n";
175 out << "}\n";
176 out << "}\n";
177
178 out << "function runSlideShow(){\n";
179 out << "if (document.all){\n";
180 if ( blend )
181 {
182 out << "document.images.SlideShow.style.filter=\"blendTrans(duration=3)\"\n";
183 out << "document.images.SlideShow.style.filter=\"blendTrans(duration=crossFadeDuration)\"\n";
184 out << "document.images.SlideShow.filters.blendTrans.Apply()\n";
185 }
186 else
187 {
188 out << "document.images.SlideShow.style.filter=\"revealTrans(duration=crossFadeDuration, transition=trans)\"\n";
189 out << "document.images.SlideShow.filters.revealTrans.Apply()\n";
190 }
191 out << "}\n";
192 out << "document.images.SlideShow.src = preLoad[j].src\n";
193 out << "document.imginfo.image.value = \"Source: \" + preLoad[j].src\n";
194 out << "if (document.all){\n";
195 if ( blend )
196 {
197 out << "document.images.SlideShow.filters.blendTrans.Play()\n";
198 }
199 else
200 {
201 out << "document.images.SlideShow.filters.revealTrans.Play()\n";
202 }
203 out << "}\n";
204 out <<"j = j + 1\n";
205 out << "if (j > (p-1)) j=0\n";
206 out << "t = setTimeout('runSlideShow()', slideShowSpeed)\n";
207 out <<"}\n";
208 out << "function restart() {\n";
209 out << "document.images.SlideShow.src = Pic[0]\n";
210 out << "}\n";
211 out << "function halt() {\n";
212 out << "t = setTimeOut('runSlideShow()', 3600*60)\n";
213 out << "}\n";
214 out <<"</script>\n";
215
216 out <<"<TITLE>Slideshow Viewer</TITLE>\n";
217 out <<"</HEAD>\n";
218 out <<"<BODY onload=\"runSlideShow()\">\n";
219 out <<"<center><H1>" << title << "</H1></center>\n";
220 out <<"<HR noshade>\n";
221 out <<"<BR>\n";
222 out <<"<p align=\"center\">\n";
223 out <<"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">\n";
224 out <<"<tr>\n";
225 out <<"<td id=\"VU\">\n";
226 out <<"<img src=\"file://" << first_img << "\" name='SlideShow' border=" << border << " >\n";
227 out << "<form name=\"imginfo\" align=\"center\">\n";
228 out << "<font size=2 family=\"Arial, Helvetica\">\n";
229 out << "<input type=\"text\" name=\"image\" size=100 value=\"Image\" >";
230 out << "</font>\n";
231 out << "<BR>\n<BR>\n";
232 out << "<input type=submit name=\"Restart\" value=\"Restart\" size=15 action=\"restart\" >\n";
233 out << "<input type=submit name=\"Stop\" value=\"Halt\" size=15 action=\"halt\" >\n";
234 out << "</form>\n";
235 out <<"</td>\n";
236 out <<"</tr>\n";
237 out <<"</table>\n";
238 out <<"<BR>\n";
239 out <<"<HR noshade>\n";
240 out <<"<P align=\"center\">\n";
241 out << "<font color=blue size=3><i>Created by Image2html Version 1.0, Copyright© Anand B Pillai (anandpillai@hotmail.com)</i></font>\n";
242 out << "<BR>\n";
243 out << "</P>\n";
244 out <<"</BODY>\n";
245 out <<"</HTML>\n";
246
247 out.close();
248
249 return 0;
250 }
251
252 void printTree( char* pathname )
253 {
254 int file_found = 1;
255 WIN32_FIND_DATA dbuff;
256 HANDLE file_handle;
257 char dirname[MAXSIZ];
258 char fullname[MAXSIZ];
259 struct _stat statbuf;
260 static int img_count = 0;
261
262 strcpy( dirname, pathname );
263
264 if ( dirname[ strlen(dirname) -1 ] != '/' )
265 strcat( dirname, "/");
266
267 strcat( dirname, "*.*");
268 file_handle = FindFirstFile( dirname, &dbuff );
269
270 if ( file_handle != INVALID_HANDLE_VALUE )
271 {
272
273 while ( file_found )
274 {
275 if ( !strcmp( dbuff.cFileName, ".") || !strcmp( dbuff.cFileName, ".."))
276 {
277 file_found = FindNextFile( file_handle, &dbuff);
278 continue;
279 }
280
281 // prepare the fullname
282 strcpy( fullname, pathname );
283 if ( fullname[ strlen(dirname) -1 ] != '/' )
284 strcat( fullname, "/");
285
286 strncat( fullname, dbuff.cFileName, MAXSIZ );
287
288 int result = _stat( fullname, &statbuf);
289
290 if ( result == 0 )
291 {
292
293 if ( statbuf.st_mode & S_IFDIR )
294 {
295 if ( opt.norecurse == 0 )
296 printTree( fullname );
297 }
298 else
299 {
300 char* fextn;
301
302 if ( (fextn = isImage( fullname )) != NULL)
303 {
304
305 // change backslash to forslash
306 for (int kk=0; kk<strlen(fullname); kk++)
307 {
308 if ( fullname[kk] == '\\' )
309 fullname[kk] = '/';
310 }
311
312 if ( img_count == 0 )
313 strcpy( first_img, fullname);
314
315 cerr << fullname << endl;
316 out << "Pic["<<img_count++<<"]" << " = " << "'file://"<< fullname <<"'\n";
317 }
318 }
319 }
320
321 file_found = FindNextFile( file_handle, &dbuff );
322 }
323
324 }
325 }
326
327 static char*
328 isImage( char* filename )
329 {
330
331 int ok=KO;
332 char* extn=NULL;
333
334 for (int i=0; i<NUM_IMG_TYPES; i++)
335 {
336 extn = strrchr( filename, '.' );
337 if (extn)
338 {
339 if (!strcmp( extn, imageExtns[i]))
340 {
341 break;
342 }
343 else
344 extn=NULL;
345 }
346 }
347
348 return extn;
349 }
350
351 static
352 int parseArgs( int argc, char* argv[], Options* opt )
353 {
354 // Initialize
355 opt->speedofshow = 5000; // default is 5 seconds
356 opt->duration = 3; // default is 3 seconds for crossfade (only supported on IE)
357 strcpy(opt->directory, "UNDEFINED");
358 opt->border=0; // default is no border
359 opt->title="SlideShow";
360
361 // Default is a reveal transition number 5 (checkerbox transition)
362 opt->blend = 0;
363 opt->transition = 5;
364 opt->norecurse = 0;
365
366 for ( int i=1; i<argc; i++ )
367 {
368 // Directory
369 if ( !strcmp( argv[i], "-d"))
370 strcpy(opt->directory, argv[i+1]);
371
372 if ( !strcmp( argv[i], "-t"))
373 opt->speedofshow = atoi(argv[i+1]);
374
375 if ( !strcmp( argv[i], "-cf"))
376 opt->duration = atoi(argv[i+1]);
377
378 if ( !strcmp( argv[i], "-b"))
379 opt->border = atoi(argv[i+1]);
380
381 if ( !strcmp( argv[i], "-tt"))
382 opt->title = argv[i+1];
383
384 if ( !strcmp( argv[i], "--blendtrans"))
385 {
386 opt->blend = 1;
387 if ( i < argc - 1 )
388 {
389 opt->duration = atoi(argv[i+1]);
390 }
391 }
392
393 if ( !strcmp( argv[i], "--revealtrans"))
394 {
395 if ( i < argc - 2 )
396 {
397 opt->blend = 0;
398 opt->duration = atoi(argv[i+1]);
399 opt->transition = atoi(argv[i+2]);
400 }
401 else
402 {
403 opt->blend = 0;
404 }
405 }
406
407 if ( !strcmp( argv[i], "-norec"))
408 {
409 opt->norecurse=1;
410 }
411 }
412
413 // directory not supplied!
414 if ( !strcmp( opt->directory, "UNDEFINED"))
415 {
416 cerr << "Error: Directory argument is needed!\n";
417 return -1;
418 }
419
420 // check for existence of directory
421 struct _stat dirbuf;
422 int result = _stat( opt->directory, &dirbuf );
423
424 if ( result == 0 )
425 {
426 if ( !(dirbuf.st_mode & S_IFDIR ) )
427 {
428 cerr << "Error: " << opt->directory << " is not a directory!\n";
429 return -1;
430 }
431 }
432 else
433 {
434 cerr << "Error: " << opt->directory << " does not exist!\n";
435 return -1;
436 }
437
438 return 0;
439 }
440