1: #!/usr/bin/perl
2:
3: # Copyright (C) 2003-2005 Robert Casties, IT-Group MPIWG
4: #
5: # This program is free software; you can redistribute it and/or modify it
6: # under the terms of the GNU General Public License as published by the Free
7: # Software Foundation; either version 2 of the License, or (at your option)
8: # any later version.
9: #
10: # Please read license.txt for the full details. A copy of the GPL may be found
11: # at http://www.gnu.org/copyleft/lgpl.html
12: #
13: # You should have received a copy of the GNU General Public License along with
14: # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15: # Place, Suite 330, Boston, MA 02111-1307 USA
16:
17: use strict;
18: use sigtrap qw(die normal-signals);
19:
20: # MPIWG libraries
21: use lib '/usr/local/mpiwg/scripts';
22: use MPIWGlib;
23:
24:
25: $| = 1; # unblock IO
26:
27: my $version = "V0.9.6 (ROC 6.1.2005)";
28:
29: $debug = 0;
30:
31: my $simulate = 0;
32:
33: my $do_descend = 1;
34:
35: my $dir_perm = 0775;
36: my $file_perm = 0664;
37:
38: umask 000; # to make shure we can actually use these perms
39:
40: my $overwrite = 0; # overwrite already converted files
41: my $synchronise = 0; # delete unmatched destination files
42:
43: # image file extensions and formats
44: my %img_type_ext = ("tif" => "TIFF", "tiff" => "TIFF", "gif" => "GIF",
45: "jpg" => "JPEG", "png" => "PNG", "dcr" => "RAW");
46: # destination image file extensions
47: my %target_ext_type = ("TIFF" => "jpg", "JPEG" => "jpg");
48:
49: # default scale settings
50: my $scale_w = 2048; # width in pixel
51: my $scale_h = 2048; # height in pixel
52: my $scale_relative = 0; # scale by relative factor instead of destination size
53: my $jpeg_quality = 75; # default JPEG compression quality
54: my $use_encoder = 0; # false: autodetect encoder
55:
56: # programs to use
57: my $identifier;
58: my $tiffinfo;
59: my $jpegloader;
60: my $tiffloader;
61: my $quantizer;
62: my $scaler;
63: my $jpegwriter;
64: my $pngwriter;
65: my $converter;
66:
67: ##########################################################################
68: # subroutines
69: #
70:
71: #
72: # checksoft()
73: #
74: # returns if all necessary external programs are installed
75: #
76: sub checksoft {
77:
78: my @softdirs = ("/usr/X11R6/bin", "/usr/bin", "/usr/local/bin");
79:
80: $identifier = findfile(\@softdirs, "identify")
81: or die("ABORT: neccessary external program not found: identify");
82: $tiffinfo = findfile(\@softdirs, "tiffinfo")
83: or die("ABORT: neccessary external program not found: tiffinfo");
84: $jpegloader = findfile(\@softdirs, "jpegtopnm")
85: or die("ABORT: neccessary external program not found: jpegtopnm");
86: $tiffloader = findfile(\@softdirs, "tifftopnm")
87: or die("ABORT: neccessary external program not found: tifftopnm");
88: $quantizer = findfile(\@softdirs, "pbmtopgm")
89: or die("ABORT: neccessary external program not found: pbmtopgm");
90: $scaler = findfile(\@softdirs, "pnmscale")
91: or die("ABORT: neccessary external program not found: pnmscale");
92: $jpegwriter = findfile(\@softdirs, "ppmtojpeg")
93: or die("ABORT: neccessary external program not found: ppmtojpeg");
94: $pngwriter = findfile(\@softdirs, "pnmtopng")
95: or die("ABORT: neccessary external program not found: pnmtopng");
96: $converter = findfile(\@softdirs, "convert")
97: or die("ABORT: neccessary external program not found: convert");
98:
99: }
100:
101:
102:
103: #
104: # findir(\@basedirs, $subdir)
105: #
106: # check directories in @basedirs+$subdir and return the first existing basedir
107: #
108: sub findir {
109: my($dirlist, $subdir) = @_;
110:
111: foreach my $dir (@$dirlist) {
112: if (-d "$dir/$subdir") {
113: return "$dir";
114: }
115: }
116: return;
117: }
118:
119: #
120: # findfile(\@basedirs, $filename)
121: #
122: # check @basedirs+$filename and return the first existing file
123: #
124: sub findfile {
125: my($dirlist, $fn) = @_;
126:
127: foreach my $dir (@$dirlist) {
128: if (-f "$dir/$fn") {
129: return "$dir/$fn";
130: }
131: }
132: return;
133: }
134:
135: #
136: # $p = cleanpath($path, $startslash).
137: #
138: # returns a pathname with trailing and starting slash removed (if
139: # $startslash is true the starting slash is not removed)
140: #
141: sub cleanpath {
142: my ($path, $startslash) = @_;
143:
144: if ($path =~ /^(\/)*(.*?)\/*$/) {
145: if ($startslash) {
146: return $1 . $2;
147: } else {
148: return $2;
149: }
150: }
151: return $path;
152: }
153:
154: #
155: # ($basename, $extension) = splitfn($filename)
156: #
157: # split filename into base and (lowercase) extension
158: #
159: sub splitfn {
160: my ($filepath) = @_;
161: if ($filepath =~ /^(.*)\.(\w+)$/) {
162: return ($1, lc($2));
163: }
164: return;
165: }
166:
167:
168: #
169: # mmkdir($dirname)
170: #
171: # create directory recursively and check permissions
172: #
173: sub mmkdir {
174: my($dirname) = @_;
175: my $newdir;
176:
177: # does the directory already exist?
178: if (-d $dirname) {
179: chmod $dir_perm, $dirname or do {
180: logger('WARNING', "unable to change permission on $dirname!");
181: };
182: return 1;
183: }
184: # split directory name by levels
185: my @dirlist = split /\//, $dirname;
186: my @newlist = ();
187: my $dir = join("/", @dirlist);
188: # test backwards which directories exist
189: while (not -d $dir) {
190: last unless ($dir);
191: # move missing elements from the end of @dirlist to @newlist
192: unshift @newlist, pop @dirlist;
193: $dir = join("/", @dirlist);
194: }
195: # create missing directories level by level
196: foreach $newdir (@newlist) {
197: push @dirlist, $newdir;
198: $dir = join("/", @dirlist);
199: mkdir "$dir", $dir_perm or do {
200: logger('ERROR', "unable to create $dir!");
201: return 0;
202: }
203: }
204: return 1;
205: }
206:
207: #
208: # ($type, $width, $height) = identify($filepath)
209: #
210: # returns type, width and height of the image using ImageMagick's identify
211: #
212: sub identify {
213: my ($filepath) = @_;
214: my $pictype = "";
215: my $picwidth = 0;
216: my $picheight = 0;
217: my $bitdepth = 0;
218: # use quickident first
219: $pictype = quickident($filepath);
220: # optimized tiff identification
221: if (($pictype)&&($pictype eq 'TIFF')) {
222: logger('DEBUG', "running tiffinfo $tiffinfo");
223: if (open(IDENT, "nice -10 $tiffinfo '$filepath' 2>/dev/null |")) {
224: while (<IDENT>) {
225: chomp;
226: # we take the biggest values, because embedded thumbnails
227: # may also show up
228: if (/Image Width:\s*(\d+)\s*Image Length:\s*(\d+)/) {
229: $picwidth = $1 if ($1 > $picwidth);
230: $picheight = $2 if ($2 > $picheight);
231: next;
232: }
233: if (/Bits\/Sample:\s*(\d+)/) {
234: $bitdepth = $1 if ($1 > $bitdepth);
235: next;
236: }
237: }
238: if ($picwidth) {
239: logger('DEBUG', "TIFF $picwidth x $picheight");
240: return ($pictype, $picwidth, $picheight, $bitdepth);
241: }
242: }
243: }
244: # run ident to get image type and dimensions
245: logger('DEBUG', "running identifier $identifier");
246: if (open(IDENT, "nice -10 $identifier -ping -format '%w %h %m\n' '$filepath' 2>/dev/null |")) {
247: my @id = <IDENT>;
248: my $picinfo = $id[0];
249: close IDENT;
250: chomp $picinfo;
251: logger('DEBUG', "PIC is '$picinfo'");
252: if ($picinfo =~ /^(\d+) (\d+) (\w+)$/) {
253: $picwidth = $1;
254: $picheight = $2;
255: $pictype = $3;
256: }
257: } else {
258: logger('DEBUG', "unable to identify $filepath!");
259: }
260: return ($pictype, $picwidth, $picheight, $bitdepth);
261: }
262:
263: #
264: # $type = quickident($filepath);
265: #
266: # returns image type based on file extension only
267: #
268: sub quickident {
269: my ($filepath) = @_;
270: logger('DEBUG', "running quickident");
271: # look at file extension
272: my ($filebase, $fileext) = splitfn($filepath);
273: if ($fileext) {
274: return $img_type_ext{$fileext};
275: }
276: return;
277: }
278:
279:
280: #
281: # $fact = scalefactor(\$args)
282: #
283: # returns the necessary scaling factor
284: #
285: sub scalefactor {
286: my ($args) = @_;
287:
288: my $srcdir = $$args{'srcdir'};
289: my $filename = $$args{'filename'};
290: my $scale_w = $$args{'scale_w'};
291: my $scale_h = $$args{'scale_h'};
292: my $scale_rel = $$args{'scale_rel'};
293: my $scale = 0;
294:
295: if ($scale_rel) {
296: # scale relative -- no size needed, only scaling factor
297: $scale = $scale_w;
298: } else {
299: # scale to size -- size needed
300: my $pictype = $$args{'pictype'};
301: my $picwidth = $$args{'picwidth'};
302: my $picheight = $$args{'picheight'};
303: if (! $picwidth) {
304: # no size yet - identify
305: ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
306: if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
307: logger('ERROR', "unable to identify $srcdir/$filename!");
308: return 0;
309: }
310: # save values
311: $$args{'pictype'} = $pictype;
312: $$args{'picwidth'} = $picwidth;
313: $$args{'picheight'} = $picheight;
314: }
315: # calculate x and y scaling factors
316: my $scale_x = $scale_w / $picwidth;
317: my $scale_y = $scale_h / $picheight;
318: # take the smallest
319: if ($scale_x < $scale_y) {
320: $scale = $scale_x;
321: logger('DEBUG', "PIC scale to width");
322: } else {
323: $scale = $scale_y;
324: logger('DEBUG', "PIC scale to height");
325: }
326: if ($scale >= 1) {
327: $scale = 1;
328: logger('DEBUG', "PIC is already smaller");
329: # continue since we may have to convert
330: }
331: }
332: return $scale;
333: }
334:
335:
336: #
337: # $error = scale_jpeg(\$args);
338: #
339: # scale JPEG images to JPEG using netpbm tools
340: #
341: # args needed: $srcdir, $filename, $destdir,
342: # $scale_w, $scale_h, $scale_rel, $picwidth, $picheight
343: #
344: sub scale_jpeg {
345: my ($args) = @_;
346:
347: my $srcdir = $$args{'srcdir'};
348: my $filename = $$args{'filename'};
349: my $destdir = $$args{'destdir'};
350: my $scale_w = $$args{'scale_w'};
351: my $scale_h = $$args{'scale_h'};
352: my $scale_rel = $$args{'scale_rel'};
353: my $scaleopt;
354:
355: # convert jpg -> jpg
356: my ($basename, $fileext) = splitfn($filename);
357: my $newfn = $basename . ".jpg";
358: logger('INFO', "Convert(jpg): $filename -> $newfn");
359: return 1 if ($simulate);
360:
361: $scaleopt = scalefactor($args);
362:
363: if (!$scaleopt) {
364: logger('ERROR', "unable to calculate scaling options!");
365: return 1;
366: }
367:
368: if ($scaleopt == 1) {
369: # is already smaller
370: logger('DEBUG', "PIC is smaller and JPEG - ignoring");
371: return 0;
372: }
373:
374: # convert
375: logger('DEBUG', "nice -10 $jpegloader '$srcdir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$destdir/$newfn' 2>/dev/null");
376: return 0 if ($simulate);
377: if (system("nice -10 $jpegloader '$srcdir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$destdir/$newfn' 2>/dev/null") != 0) {
378: logger('ERROR', "error converting '$srcdir/$filename'!");
379: if (! -s "$destdir/$newfn") {
380: # file broken (size 0)
381: logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
382: unlink "$destdir/$newfn";
383: }
384: return 1;
385: }
386:
387: # change permissions
388: chmod $file_perm, "$destdir/$newfn" or
389: logger('WARNING', "unable to set permission on '$destdir/$newfn'");
390:
391: if (! -s "$destdir/$newfn") {
392: # file broken (size 0)
393: logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
394: unlink "$destdir/$newfn";
395: return 1;
396: }
397: return 0;
398: }
399:
400:
401: #
402: # $error = scale_tiff_jpeg2(\$args);
403: #
404: # scale TIFF images to JPEG using ImageMagick convert
405: #
406: # args needed: $srcdir, $filename, $destdir,
407: # $scale_w, $scale_h, $scale_rel, $picwidth, $picheight
408: #
409: sub scale_tiff_jpeg2 {
410: my ($args) = @_;
411:
412: my $srcdir = $$args{'srcdir'};
413: my $filename = $$args{'filename'};
414: my $destdir = $$args{'destdir'};
415: my $scale_w = $$args{'scale_w'};
416: my $scale_h = $$args{'scale_h'};
417: my $scale_rel = $$args{'scale_rel'};
418: my $scaleopt;
419:
420: my ($basename, $fileext) = splitfn($filename);
421: my $newfn = $basename . ".jpg";
422: logger('INFO', "Convert(tiff2): $filename -> $newfn");
423:
424: if ($scale_rel) {
425: my $per_scale = 100 * $scale_w;
426: logger('DEBUG', "nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null");
427: return 0 if ($simulate);
428: if (system("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null\n") != 0) {
429: logger('ERROR', "error converting '$srcdir/$filename'!");
430: return 1;
431: }
432: } else {
433: logger('DEBUG', "nice -10 $converter -quality $jpeg_quality -scale ${scale_w}x${scale_h} '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null");
434: return 0 if ($simulate);
435: if (system("nice -10 $converter -quality $jpeg_quality -scale ${scale_w}x${scale_h} '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null\n") != 0) {
436: logger('ERROR', "error converting '$srcdir/$filename'!");
437: if (! -s "$destdir/$newfn") {
438: # file broken (size 0)
439: logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
440: unlink "$destdir/$newfn";
441: }
442: return 1;
443: }
444: }
445:
446: # change permissions
447: chmod $file_perm, "$destdir/$newfn" or
448: logger('WARNING', "unable to set permission on '$destdir/$newfn'");
449:
450: return 0;
451: }
452:
453:
454: #
455: # $error = scale_tiff_jpeg(\$args);
456: #
457: # scale TIFF images to JPEG using netpbm tools
458: #
459: # args needed: $srcdir, $filename, $destdir,
460: # $scale_w, $scale_h, $scale_rel, $picwidth, $picheight
461: #
462: sub scale_tiff_jpeg {
463: my ($args) = @_;
464:
465: my $srcdir = $$args{'srcdir'};
466: my $filename = $$args{'filename'};
467: my $destdir = $$args{'destdir'};
468: my $bitdepth = $$args{'bitdepth'};
469: my $scale_w = $$args{'scale_w'};
470: my $scale_h = $$args{'scale_h'};
471: my $scale_rel = $$args{'scale_rel'};
472: my $scaleopt;
473:
474: # convert jpg -> jpg
475: my ($basename, $fileext) = splitfn($filename);
476: my $newfn = $basename . ".jpg";
477: logger('INFO', "Convert(tiff1): $filename -> $newfn");
478: return 1 if ($simulate);
479:
480: $scaleopt = scalefactor($args);
481:
482: if (!$scaleopt) {
483: logger('ERROR', "unable to calculate scaling options!");
484: return 1;
485: }
486:
487: # convert
488: my $cmd = "nice -10 $tiffloader \'$srcdir/$filename\' 2>/dev/null ";
489: if ($bitdepth == 1) {
490: # antialiasing bilevel images
491: $cmd .= "| nice -10 $quantizer 2 2 2>/dev/null ";
492: }
493: $cmd .= "| nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter --quality $jpeg_quality > '$destdir/$newfn' 2>/dev/null";
494: logger('DEBUG', "$cmd");
495: return 0 if ($simulate);
496: if (system($cmd) != 0) {
497: logger('ERROR', "error converting '$srcdir/$filename'!");
498: if (! -s "$destdir/$newfn") {
499: # file broken (size 0)
500: logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
501: unlink "$destdir/$newfn";
502: }
503: return 1;
504: }
505:
506: # change permissions
507: chmod $file_perm, "$destdir/$newfn" or
508: logger('WARNING', "unable to set permission on '$destdir/$newfn'");
509:
510: return 0;
511: }
512:
513:
514:
515: #
516: # $error = scale_tiff_png(\$args);
517: #
518: # scale TIFF images to PNG using netpbm tools
519: #
520: # args needed: $srcdir, $filename, $destdir,
521: # $scale_w, $scale_h, $scale_rel, $picwidth, $picheight
522: #
523: sub scale_tiff_png {
524: my ($args) = @_;
525:
526: my $srcdir = $$args{'srcdir'};
527: my $filename = $$args{'filename'};
528: my $destdir = $$args{'destdir'};
529: my $bitdepth = $$args{'bitdepth'};
530: my $scale_w = $$args{'scale_w'};
531: my $scale_h = $$args{'scale_h'};
532: my $scale_rel = $$args{'scale_rel'};
533: my $scaleopt;
534:
535: # convert tif -> png
536: my ($basename, $fileext) = splitfn($filename);
537: my $newfn = $basename . ".png";
538: logger('INFO', "Convert(tiff3): $filename -> $newfn");
539:
540: $scaleopt = scalefactor($args);
541:
542: if (!$scaleopt) {
543: logger('ERROR', "unable to calculate scaling options!");
544: return 1;
545: }
546:
547: # convert
548: my $cmd = "nice -10 $tiffloader \'$srcdir/$filename\' 2>/dev/null ";
549: if ($bitdepth == 1) {
550: # antialiasing bilevel images
551: $cmd .= "| nice -10 $quantizer 2 2 2>/dev/null ";
552: }
553: $cmd .= "| nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > '$destdir/$newfn' 2>/dev/null";
554: logger('DEBUG', "$cmd");
555: return 0 if ($simulate);
556: if (system($cmd) != 0) {
557: logger('ERROR', "error converting '$srcdir/$filename'!");
558: if (! -s "$destdir/$newfn") {
559: # file broken (size 0)
560: logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
561: unlink "$destdir/$newfn";
562: }
563: return 1;
564: }
565:
566: # change permissions
567: chmod $file_perm, "$destdir/$newfn" or
568: logger('WARNING', "unable to set permission on '$destdir/$newfn'");
569:
570: return 0;
571: }
572:
573:
574: #
575: # $error = convert_file($srcdir, $filename, $destdir);
576: #
577: # convert file
578: #
579: sub convert_file {
580: my($srcdir, $filename, $destdir, $filelist) = @_;
581: my $filebase;
582: my $fileext;
583: my $newfn;
584: my $pictype;
585: my $picwidth;
586: my $picheight;
587: my $bitdepth;
588: my $error = 0;
589:
590: logger('DEBUG', "convert_file ($srcdir, $filename, $destdir)");
591:
592: if (not (( -f "$srcdir/$filename") && (-r _))) {
593: logger('ERROR', "unable to read file '$srcdir/$filename'");
594: return 1;
595: }
596:
597: # get base name and extension
598: ($filebase, $fileext) = splitfn($filename);
599:
600: #
601: # quick check if target image exists
602: #
603: $pictype = quickident("$srcdir/$filename");
604: if ($pictype) {
605: if ($pictype eq "RAW") {
606: logger('DEBUG', "skipping raw file '$srcdir/$filename'");
607: return 0;
608: }
609: my $newext = $target_ext_type{$pictype};
610: if ($newext) {
611: $newfn = $filebase . ".$newext";
612: logger('DEBUG', "adding $destdir/$newfn'");
613: $$filelist{"$destdir/$newfn"} = $filename;
614: # check if file exists
615: if (-f "$destdir/$newfn") {
616: logger('DEBUG', "CONV file exists: $newfn");
617: if (! $overwrite) {
618: # compare age with source file
619: if (-M "$destdir/$newfn" > -M "$srcdir/$filename") {
620: logger('DEBUG', "CONV file is older: $newfn");
621: } else {
622: logger('INFO', "File already converted: $newfn");
623: return 0;
624: }
625: }
626: }
627: } else {
628: logger('DEBUG', "target extension for $pictype unknown!");
629: }
630: } else {
631: # quick ident failed -- do it slowly
632: ($pictype, $picwidth, $picheight, $bitdepth) = identify("$srcdir/$filename");
633: if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
634: logger('WARNING', "unknown file type '$srcdir/$filename'");
635: return 0;
636: }
637: }
638:
639: # collect arguments for the conversion
640: my %args;
641: $args{'srcdir'} = $srcdir;
642: $args{'destdir'} = $destdir;
643: $args{'filename'} = $filename;
644: $args{'pictype'} = $pictype;
645: $args{'picwidth'} = $picwidth;
646: $args{'picheight'} = $picheight;
647: $args{'bitdepth'} = $bitdepth;
648: $args{'srcdir'} = $srcdir;
649: $args{'scale_w'} = $scale_w;
650: $args{'scale_h'} = $scale_h;
651: $args{'scale_rel'} = $scale_relative;
652:
653: # decide conversion based on image type and encoding preferences
654: if ($pictype eq 'JPEG') {
655: $args{'jpeg_qual'} = $jpeg_quality;
656: #default encoder
657: $error = scale_jpeg(\%args);
658: } elsif ($pictype eq 'TIFF') {
659: if ($use_encoder) {
660: # use specific encoder
661: if ($use_encoder eq 'tiff_jpeg') {
662: $error = scale_tiff_jpeg(\%args);
663: } elsif ($use_encoder eq 'tiff_jpeg2') {
664: $error = scale_tiff_jpeg2(\%args);
665: } elsif ($use_encoder eq 'tiff_png') {
666: $error = scale_tiff_png(\%args);
667: }
668: } else {
669: # default
670: $error = scale_tiff_jpeg(\%args);
671: }
672: } else {
673: logger('WARNING', "unknown file type: $pictype ($srcdir/$filename)");
674: }
675: return $error;
676: }
677:
678:
679: #
680: # walk_convert_dir($dirname)
681: #
682: # Descend recursively through $dirname and work on all files
683: #
684: sub walk_convert_dir {
685: my($srcdir, $workdir, $destdir, $filelist) = @_;
686: my $errcnt = 0;
687: my $newfn;
688:
689: opendir WORKDIR, "$srcdir/$workdir" or do {
690: logger('ERROR', "Unable to open directory $srcdir/$workdir!");
691: return 0;
692: };
693:
694: my @dirlist = readdir(WORKDIR);
695:
696: closedir WORKDIR;
697:
698: # check all directories first
699: if ($do_descend) {
700: foreach (sort @dirlist) {
701: # skip dot-directories
702: next if (/^[.]+$/);
703: # skip junk directories
704: next if ($junk_files{$_});
705: # recurse through the rest
706: if (-d "$srcdir/$workdir/$_") {
707: walk_convert_dir($srcdir, "$workdir/$_", $destdir, $filelist);
708: }
709: }
710: }
711:
712: logger('INFO', "Working on $workdir");
713: logger('INFO', "Reading from $srcdir/$workdir.");
714: logger('INFO', "Writing to $destdir/$workdir");
715:
716: # create destination directory
717: if (not ($simulate)) {
718: mmkdir("$destdir/$workdir") or do {
719: logger("ERROR", "unable to create directory '$destdir/$workdir'");
720: $errcnt++;
721: return 0;
722: };
723: }
724:
725: # check all files in this directory
726: foreach (sort @dirlist) {
727: # skip dot-files
728: next if (/^[.]+.*$/);
729: # try to convert the rest
730: if (-f "$srcdir/$workdir/$_") {
731: $errcnt += convert_file("$srcdir/$workdir", "$_", "$destdir/$workdir", $filelist);
732: }
733: }
734:
735: if ($errcnt) {
736: logger('INFO', "There were $errcnt errors converting '$workdir'!");
737: } else {
738: logger('INFO', "Finished converting $workdir!");
739: }
740:
741: return 1;
742: }
743:
744:
745: #
746: # convert_dir($from_dir)
747: #
748: # Convert directory "from_dir" and its subdirectories
749: #
750: sub convert_dir {
751: my ($srcdir, $workdir, $destdir) = @_;
752: my %files = ();
753:
754: logger('INFO', "** Converting Scans **");
755:
756: if (-d "$srcdir/$workdir") {
757: # it's a dirrectory
758: logger('INFO', "Starting in directory '$srcdir/$workdir'");
759: walk_convert_dir($srcdir, $workdir, $destdir, \%files);
760: if ($synchronise) {
761: logger('INFO', "Removing unmatched files in '$destdir/$workdir'");
762: remove_unmatched_files("$destdir/$workdir", \%files);
763: }
764: # touch source directory so digilib rescans the thumbnails
765: #logger('DEBUG', "/usr/bin/touch $source_base_dirs[0]/$workdir");
766: system("/usr/bin/touch '$srcdir/$workdir'");
767: } elsif (-f _) {
768: # it's a file
769: logger('INFO', "Converting file '$srcdir/$workdir'");
770: convert_file($srcdir, $workdir, $destdir);
771: # touch source parent directory so digilib rescans the thumbnails
772: my $pdir = "$srcdir/$workdir";
773: # chop off after the last slash
774: $pdir =~ s/\/[^\/]+$/\//;
775: system("/usr/bin/touch '$pdir'");
776: }
777:
778: logger('DONE', "** Finished converting scans **");
779: return 1;
780: }
781:
782:
783:
784: #
785: # remove_unmatched_files($basedir, \%files)
786: #
787: # removes all files from $basedir and its subdirectories that are not
788: # in %files
789: #
790: sub remove_unmatched_files {
791: my ($basedir, $files) = @_;
792: my $cnt = 0;
793:
794: if (! opendir DIR, $basedir) {
795: logger('ERROR', "directory $basedir doesn't exist (in remove_unmatched_files)");
796: return 0;
797: }
798: my @dirfiles = readdir DIR;
799: foreach my $fn (@dirfiles) {
800: # ignore names starting with a dot
801: next if ($fn =~ /^\./);
802: # ignore other silly files
803: next if ($junk_files{$fn});
804:
805: $cnt++;
806: my $f = "$basedir/$fn";
807: #print "fs_file: \"$f\"\n";
808: if (-f $f) {
809: #print " is file\n";
810: logger('DEBUG', "checking '$f'");
811: if (not exists($$files{$f})) {
812: logger('DEBUG', "removing orphaned file $f");
813: unlink $f;
814: }
815: } elsif (-d _) {
816: # recurse into directory
817: $cnt += remove_unmatched_files($f, $files);
818: # delete if its empty
819: rmdir $f;
820: }
821: }
822: return $cnt;
823: }
824:
825:
826:
827: ###############################################################
828: ## Main
829:
830: if ($#ARGV < 3) {
831: print "Scale-O-Mat $version\n";
832: print " use: scaleomat.pl -src=src-base -dest=dest-base -dir=workdir [...]\n";
833: print " reads from scr-base/workdir and writes to dest-base/workdir\n";
834: print " -scaleto=destination size (S or WxH)\n";
835: print " -scaleby=magnification factor.\n";
836: print " -jpegqual=JPEG quality (0-100)\n";
837: print " -replace=yes replaces existing files (default=update).\n";
838: print " -sync=yes delete unmatched file in destination (default=ignore).\n";
839: print " -encoder=tiff_png|tiff_jpeg|tiff_jpeg2\n";
840: exit 1;
841: }
842:
843: # test software installation
844: checksoft();
845:
846: # read command line parameters
847: my $args = parseargs();
848:
849: # source dir
850: my $srcdir = cleanpath($$args{'src'}, 1);
851:
852: # destination dir
853: my $destdir = cleanpath($$args{'dest'}, 1);
854:
855: # working dir
856: my $workdir = cleanpath($$args{'dir'});
857:
858: # destination size
859: if ($$args{'scaleby'}) {
860: $scale_relative = 1;
861: $scale_w = $$args{'scaleby'};
862: logger('INFO', "Scaling relative by factor $scale_w");
863: }
864: if ($$args{'scaleto'}) {
865: $scale_relative = 0;
866: if ($$args{'scaleto'} =~ /(\d+)x(\d+)/) {
867: $scale_w = $1;
868: $scale_h = $2;
869: } else {
870: $scale_w = $$args{'scaleto'};
871: $scale_h = $$args{'scaleto'};
872: }
873: logger('INFO', "Scaling absolute to size $scale_w x $scale_h");
874: }
875:
876: # JPEG quality
877: if ($$args{'jpegqual'}) {
878: logger('INFO', "JPEG quality set to '$$args{'jpegqual'}'!");
879: $jpeg_quality = $$args{'jpegqual'};
880: }
881:
882: # force encoder
883: if ($$args{'encoder'}) {
884: logger('INFO', "Using encoder '$$args{'encoder'}'!");
885: $use_encoder = $$args{'encoder'};
886: }
887:
888: # Overwrite
889: if ($$args{'replace'}) {
890: logger('INFO', "Set to overwrite existing files!");
891: $overwrite = 1;
892: }
893:
894: # Synchronise
895: if ($$args{'sync'}) {
896: logger('INFO', "Set to delete unmatched files!");
897: $synchronise = 1;
898: }
899:
900: # debug
901: if ($$args{'debug'}) {
902: logger('INFO', "Set debug level to $$args{'debug'}!");
903: $debug = $$args{'debug'};
904: }
905:
906: # simulate
907: if ($$args{'simulate'}) {
908: logger('INFO', "Set to simulate operation only ($$args{'simulate'})!");
909: $simulate = $$args{'simulate'};
910: }
911:
912: convert_dir($srcdir, $workdir, $destdir);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>