Annotation of scaleomat/scaleomat.pl, revision 1.1.1.1
1.1 casties 1: #!/usr/bin/perl
2:
3: $| = 1; # unblock IO
4:
5: $version = "V0.7 (ROC 23.12.2003)";
6:
7: $debug = 0;
8: $simulate = 0;
9:
10: $do_descend = 1;
11:
12: @source_base_dirs = ("/docuserver/images");
13: $dest_base_dir = "/docuserver/scaled/small";
14: $dir_perm = 0775;
15: $file_perm = 0664;
16:
17: umask 000; # to make shure we can actually use these perms
18:
19: $dont_overwrite = 1; # don't overwrite already converted files
20:
21: @imgfile_ext = ("tif", "tiff", "gif", "jpg", "png");
22:
23: $target_size = 2048; # pixel of longest side
24: $scale_relative = 0; # scale by relative factor instead of destination size
25: $jpeg_quality = 75; # default JPEG compression quality
26:
27: ##########################################################################
28: # subroutines
29: #
30:
31: #
32: # checksoft()
33: #
34: # returns if all necessary external programs are installed
35: #
36: sub checksoft {
37:
38: my @softdirs = ("/usr/X11R6/bin", "/usr/bin", "/usr/local/bin");
39:
40: $identifier = findfile(\@softdirs, "identify")
41: or die("ABORT: neccessary external program not found: identify");
42: $jpegloader = findfile(\@softdirs, "jpegtopnm")
43: or die("ABORT: neccessary external program not found: jpegtopnm");
44: $tiffloader = findfile(\@softdirs, "tifftopnm")
45: or die("ABORT: neccessary external program not found: tifftopnm");
46: $quantizer = findfile(\@softdirs, "pbmtopgm")
47: or die("ABORT: neccessary external program not found: pbmtopgm");
48: $scaler = findfile(\@softdirs, "pnmscale")
49: or die("ABORT: neccessary external program not found: pnmscale");
50: $jpegwriter = findfile(\@softdirs, "ppmtojpeg")
51: or die("ABORT: neccessary external program not found: ppmtojpeg");
52: $pngwriter = findfile(\@softdirs, "pnmtopng")
53: or die("ABORT: neccessary external program not found: pnmtopng");
54: $converter = findfile(\@softdirs, "convert")
55: or die("ABORT: neccessary external program not found: convert");
56:
57: }
58:
59:
60:
61: #
62: # dprint($message)
63: #
64: # print if $debug = 1
65: #
66: sub dprint {
67: my ($msg) = @_;
68:
69: if ($debug) {
70: print "$msg";
71: }
72: }
73:
74:
75:
76: #
77: # findir(\@basedirs, $subdir)
78: #
79: # check directories in @basedirs+$subdir and return the first existing basedir
80: #
81: sub findir {
82: my($dirlist, $subdir) = @_;
83:
84: foreach my $dir (@$dirlist) {
85: if (-d "$dir/$subdir") {
86: return "$dir";
87: }
88: }
89: return;
90: }
91:
92: #
93: # findfile(\@basedirs, $filename)
94: #
95: # check @basedirs+$filename and return the first existing file
96: #
97: sub findfile {
98: my($dirlist, $fn) = @_;
99:
100: foreach my $dir (@$dirlist) {
101: if (-f "$dir/$fn") {
102: return "$dir/$fn";
103: }
104: }
105: return;
106: }
107:
108:
109: #
110: # mmkdir($dirname)
111: #
112: # create directory recursively and check permissions
113: #
114: sub mmkdir {
115: my($dirname) = @_;
116: my $newdir;
117:
118: # does the directory already exist?
119: if (-d $dir) {
120: chmod $dir_perm, $dir or do {
121: print "ERROR: unable to change permission on $dir!\n";
122: return 0;
123: };
124: return 1;
125: }
126: # split directory name by levels
127: my @dirlist = split /\//, $dirname;
128: my @newlist = ();
129: my $dir = join("/", @dirlist);
130: # test backwards which directories exist
131: while (not -d $dir) {
132: # move missing elements from the end of @dirlist to @newlist
133: unshift @newlist, pop @dirlist;
134: $dir = join("/", @dirlist);
135: }
136: # create missing directories level by level
137: foreach $newdir (@newlist) {
138: push @dirlist, $newdir;
139: $dir = join("/", @dirlist);
140: mkdir "$dir", $dir_perm or do {
141: print "ERROR: unable to create $dir!\n";
142: return 0;
143: }
144: }
145: return 1;
146: }
147:
148: #
149: # dir_ok($dirname)
150: #
151: # check directory name against evil
152: #
153: sub dir_ok {
154: my($dirname) = @_;
155:
156: if ($dirname eq "") {
157: print "ERROR: DIR mustn't be empty!\n";
158: return 0;
159: }
160: if ($dirname =~ /\.\./) {
161: print "ERROR: DIR mustn't backref!\n";
162: return 0;
163: }
164: if ($dirname =~ /[|<>]+/) {
165: print "ERROR: DIR mustn't be special!\n";
166: return 0;
167: }
168: return 1;
169: }
170:
171:
172: #
173: # convert_file($filename)
174: #
175: # convert file
176: #
177: sub convert_file {
178: my($basedir, $filename) = @_;
179: my $newfn;
180: my $pictype;
181: my $picwidth;
182: my $picheight;
183: my $scaleopt = 0.3;
184:
185: if (not (( -f "$basedir/$filename") && (-r _))) {
186: print "ERROR: unable to read file '$basedir/$filename'\n;";
187: return 0;
188: }
189:
190: #
191: # run ident first to get image type and dimensions
192: # calculate scaling factor based on destination size or factor
193: #
194: if (open(IDENT, "nice -10 $identifier -ping -format '%w %h %m\n' '$basedir/$filename' 2>/dev/null|")) {
195: my @id = <IDENT>;
196: my $picinfo = $id[0];
197: close IDENT;
198: chomp $picinfo;
199: dprint "INFO: PIC is $picinfo\n";
200: if ($picinfo =~ /^(\d+) (\d+) (\w+)$/) {
201: $picwidth = $1;
202: $picheight = $2;
203: $pictype = $3;
204: if ($scale_relative) {
205: $scaleopt = $target_size;
206: } else {
207: if ($picheight > $picwidth) {
208: $scaleopt = $target_size / $picheight;
209: dprint "INFO: PIC is portrait\n";
210: } else {
211: $scaleopt = $target_size / $picwidth;
212: dprint "INFO: PIC is landscape\n";
213: }
214: if ($scaleopt >= 1) {
215: $scaleopt = 1;
216: dprint "INFO: PIC is already smaller\n";
217: }
218: }
219: }
220: }
221:
222: #
223: # scale JPEG images to JPEG using netpbm tools
224: #
225: if ($pictype eq 'JPEG') {
226: # convert jpg -> jpg
227: $newfn = $filename;
228: $newfn =~ s/\.\w+$/.jpg/;
229: if (-f "$dest_base_dir/$newfn") {
230: dprint "INFO CONV file exists: $newfn\n";
231: if ($dont_overwrite) {
232: print "INFO: File already converted: $newfn\n";
233: return 1;
234: }
235: }
236: print "INFO: Convert(jpg): $filename -> $newfn\n";
237: return 1 if ($simulate);
238: dprint("nice -10 $jpegloader '$basedir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$dest_base_dir/$newfn' 2>/dev/null\n");
239: if (system("nice -10 $jpegloader '$basedir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$dest_base_dir/$newfn' 2>/dev/null") != 0) {
240: return 0;
241: }
242: chmod $file_perm, "$dest_base_dir/$newfn" or
243: print "WARNING: unable to set permission on '$dest_base_dir/$newfn'\n";
244: return 1;
245: }
246:
247: #
248: # scale TIFF images to JPEG using convert
249: # (slower but netpbm doesn't always work)
250: #
251: if ($pictype eq 'TIFF') {
252: # convert tif -> jpg
253: $newfn = $filename;
254: $newfn =~ s/\.\w+$/.jpg/;
255: if (-f "$dest_base_dir/$newfn") {
256: dprint "INFO: CONV file exists: $newfn\n";
257: if ($dont_overwrite) {
258: print "INFO: File already converted: $newfn\n";
259: return 1;
260: }
261: }
262: print "INFO: Convert(tif): $filename -> $newfn\n";
263: if ($scale_relative) {
264: my $per_scale = 100 * $scaleopt;
265: dprint("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% $basedir/$filename $dest_base_dir/$newfn 2>/dev/null\n");
266: return 1 if ($simulate);
267: if (system("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$basedir/$filename' '$dest_base_dir/$newfn' 2>/dev/null\n") != 0) {
268: return 0;
269: }
270: } else {
271: dprint("nice -10 $converter -quality $jpeg_quality -scale ${target_size}x${target_size} $basedir/$filename $dest_base_dir/$newfn 2>/dev/null\n");
272: return 1 if ($simulate);
273: if (system("nice -10 $converter -quality $jpeg_quality -scale ${target_size}x${target_size} '$basedir/$filename' '$dest_base_dir/$newfn' 2>/dev/null\n") != 0) {
274: return 0;
275: }
276: }
277: chmod $file_perm, "$dest_base_dir/$newfn" or
278: print "WARNING: unable to set permission on '$newfn'\n;";
279: return 1;
280: }
281:
282: #
283: # convert TIFF to PNG using netpbm tools (not used any more)
284: #
285: if ($pictype eq 'TIFF_old') {
286: # convert tif -> png
287: $newfn = $filename;
288: $newfn =~ s/\.\w+$/.png/;
289: if (-f "$dest_base_dir/$newfn") {
290: dprint "INFO: CONV file exists: $newfn\n";
291: if ($dont_overwrite) {
292: print "INFO: File already converted: $newfn\n";
293: return 1;
294: }
295: }
296: print "INFO: Convert(tif): $filename -> $newfn\n";
297: return 1 if ($simulate);
298: dprint("nice -10 $tiffloader $basedir/$filename 2>/dev/null | nice -10 $quantizer 2 2 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > $dest_base_dir/$newfn 2>/dev/null\n");
299: if (system("nice -10 $tiffloader $basedir/$filename 2>/dev/null | nice -10 $quantizer 2 2 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > $dest_base_dir/$newfn 2>/dev/null") != 0) {
300: return 0;
301: }
302: chmod $file_perm, "$dest_base_dir/$newfn" or
303: print "WARNING: unable to set permission on '$newfn'\n;";
304: return 1;
305: }
306:
307: print "WARNING: unknown file type: '$basedir/$filename'\n;";
308: return 0;
309: }
310:
311:
312: #
313: # walk_convert_dir($dirname)
314: #
315: # Descend recursively through $dirname and work on all files
316: #
317: sub walk_convert_dir {
318: my($workdir) = @_;
319: my $errcnt = 0;
320: my $newfn;
321:
322: my $basedir = findir(\@source_base_dirs, $workdir);
323:
324: opendir WORKDIR, "$basedir/$workdir" or do {
325: print "ERROR: Unable to open directory $basedir/$workdir!\n";
326: return 0;
327: };
328:
329: my @dirlist = readdir(WORKDIR);
330:
331: closedir WORKDIR;
332:
333: if ($do_descend) {
334: foreach (sort @dirlist) {
335: if (/^[.]+$/) {
336: next;
337: }
338: if (-d "$basedir/$workdir/$_") {
339: walk_convert_dir("$workdir/$_");
340: }
341: }
342: }
343:
344: print "INFO: Working on $workdir\n";
345: print "INFO: Reading from $basedir.\n";
346: print "INFO: Writing to $dest_base_dir\n";
347:
348: if (not ($simulate)) {
349: mmkdir("$dest_base_dir/$workdir") or do {
350: print "ERROR: unable to create directory '$dest_base_dir/$workdir'\n;";
351: $errcnt++;
352: return 0;
353: };
354: if ($dont_overwrite == 0) {
355: foreach (@imgfile_ext) {
356: system("rm -f $dest_base_dir/$workdir/*.$_");
357: }
358: }
359: }
360:
361: foreach (sort @dirlist) {
362: if (/^[.]+.*$/) {
363: next;
364: }
365: if (-f "$basedir/$workdir/$_") {
366: if (convert_file($basedir, "$workdir/$_") == 0) {
367: $errcnt++;
368: }
369: }
370: }
371:
372: if ($errcnt) {
373: print "INFO: There were errors converting $workdir!\n";
374: } else {
375: print "INFO: Finished converting $workdir!\n";
376: }
377:
378: return 1;
379: }
380:
381:
382: #
383: # convert_dir($from_dir)
384: #
385: # Convert directory "from_dir" and its subdirectories
386: #
387: sub convert_dir {
388: my ($workdir) = @_;
389:
390: print "INFO: ** Converting Scans **\n";
391: print "INFO: Starting in directory '$workdir'\n";
392:
393: dir_ok($workdir) or die("ABORT: Illegal directory name '$workdir'!\n");
394:
395: walk_convert_dir($workdir);
396:
397: # touch source directory so digilib rescans the thumbnails
398: #print "DEBUG:/usr/bin/touch $source_base_dirs[0]/$workdir\n";
399: system("/usr/bin/touch $source_base_dirs[0]/$workdir");
400:
401: print "DONE: ** Finished converting scans **\n";
402: return 1;
403: }
404:
405:
406:
407:
408:
409:
410: ###############################################################
411: ## Main
412:
413: if ($#ARGV < 0) {
414: print "Scale-O-Mat $version\n";
415: print " use: scaleomat.pl hires-dir dest-base size [quality] [--replace]\n";
416: print " - if hires-dir starts with '/' then it's absolute.\n";
417: print " - if size starts with 'x' then it's magnification factor.\n";
418: print " - quality is JPEG quality (0-100)\n";
419: print " - --replace replaces existing files (default=skip).\n";
420: exit 1;
421: }
422:
423: # test software installation
424: checksoft;
425:
426: # parameter 1 is destination dir
427: if ($#ARGV > 0) {
428: $dest_base_dir = $ARGV[1];
429: }
430:
431: # parameter 2 is destination size (or factor when starting with "x")
432: if ($#ARGV > 1) {
433: if ($ARGV[2] =~ /^x([\d.]+)/) {
434: $scale_relative = 1;
435: $target_size = $1;
436: print "INFO: scaling relative by factor $target_size\n";
437: } else {
438: $scale_relative = 0;
439: $target_size = $ARGV[2];
440: print "INFO: scaling absolute to size $target_size\n";
441: }
442: }
443:
444: # optional parameters are JPEG quality or --replace
445: if ($#ARGV > 2) {
446: for ($i = 3; $i <= $#ARGV; $i++) {
447: $s = $ARGV[$i];
448: if ($s eq "--replace") {
449: print "INFO: set to overwrite existing files!\n";
450: $dont_overwrite = 0;
451: } else {
452: print "INFO: JPEG quality set to '$s'!\n";
453: $jpeg_quality = $s;
454: }
455: }
456: }
457:
458: # convert all files in the directory
459: my $srcdir = $ARGV[0];
460: if ($srcdir =~ /^\//) {
461: # if source dir starts with / then ist's absolute
462: $source_base_dirs[0] = "/";
463: }
464: convert_dir($srcdir);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>