Annotation of scaleomat/scaleomat.pl, revision 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>